#![allow(warnings)]
use std::{rc::Rc, cell::RefCell, sync::Arc, error};

use once_cell::sync::Lazy;

use crate::{classfile::{MemberInfo, LineNumberTableAttribute, ExceptionsAttribute}, rtda::heap::class_name_helper::to_class_name};

use super::{class::Class, access_flags::{ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC, ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT}, method_descriptor_parser::MethodDescriptorParser, ExceptionTable, method_descriptor::MethodDescriptor};


#[derive(Default, Clone)]
pub struct Method {
    access_flags: u16, // 访问标志
    name: String, // 字段名称
    descriptor: String, // 描述符
    signature: String,
    annotation_data: Vec<u8>, // RuntimeVisibleAnnotations_attribute
    class: Option<Arc<Class>>,
    // class_member ↑
    max_stack: usize, // 操作数栈大小
    max_locals: usize, // 局部变量表大小
    code: Vec<u8>, // 字节码指令
    arg_slot_count: usize, // 参数数量
    exception_table: ExceptionTable,
    line_number_table: Option<LineNumberTableAttribute>,
    parsed_descriptor: MethodDescriptor,
    execeptions: Option<ExceptionsAttribute>,
    parameter_annotation_data: Vec<u8>, // RuntimeVisibleParameterAnnotations_attribute
    annotation_default_data: Vec<u8>, // AnnotationDefault_attribute
}

unsafe impl Send for Method {}


// class_member
impl Method {
    // 复制字段信息，访问标志、字段名称、描述符
    pub fn copy_member_info(&mut self, member_info: &MemberInfo) {
        self.access_flags = member_info.access_flags();
        self.name = member_info.name();
        self.descriptor = member_info.descriptor();
    }

    pub fn is_public(&self) -> bool {
        0 != self.access_flags & ACC_PUBLIC
    }

    pub fn is_private(&self) -> bool {
        0 != self.access_flags & ACC_PRIVATE
    }

    pub fn is_protected(&self) -> bool {
        0 != self.access_flags & ACC_PROTECTED
    }

    pub fn is_static(&self) -> bool {
        0 != self.access_flags & ACC_STATIC
    }

    pub fn is_final(&self) -> bool {
        0 != self.access_flags & ACC_FINAL
    }

    pub fn is_synthetic(&self) -> bool {
        0 != self.access_flags & ACC_SYNTHETIC
    }

    // getters
    pub fn get_access_flags(&self) -> u16 {
        self.access_flags
    }

    pub fn get_name(&self) -> String {
        self.name.clone()
    }

    pub fn get_descriptor(&self) -> String {
        self.descriptor.clone()
    }

    pub fn get_signature(&self) -> String {
        self.signature.clone()
    }

    pub fn get_annotation_data(&self) -> &Vec<u8> {
        &self.annotation_data
    }

    pub fn get_class(&self) -> Arc<Class> {
        self.class.clone().unwrap()
    }

    // 是否能访问 jvms 5.4.4
    pub fn is_accessible_to(&self, d: Arc<Class>) -> bool {
        // public
        if self.is_public() {
            return true;
        }
        let c = self.get_class();
        // protected仅允许子类和同包下的文件访问
        if self.is_protected() {
            return Arc::ptr_eq(&c, &d) || d.is_sub_class_of(&c) || c.get_package_name() == d.get_package_name();
        }
        // 默认访问权，仅同包下文件可访问
        if !self.is_private() {
            return c.get_package_name() == d.get_package_name();
        }
        // 是否指向统一class
        if Arc::ptr_eq(&c, &d) {
            return true;
        }
        // 231214 新增判断匿名类
        match (c.original_class(), d.original_class()) {
            (Some(o1), Some(o2)) => Arc::ptr_eq(&o1, &o2),
            (Some(o), None) => Arc::ptr_eq(&o, &d),
            (None, Some(o)) => Arc::ptr_eq(&c, &o),
            _ => false
        }
    }
}

impl Method {
    // 由class_file中的method方法生成
    pub fn new_methods(class: Arc<Class>, cf_methods: &Vec<MemberInfo>) -> Vec<Arc<Method>> {
        cf_methods.iter().map(|cf_method| Arc::new(Self::new_method(class.clone(), cf_method))).collect()
    }

    // 由class_file中的method方法生成
    fn new_method(class: Arc<Class>, cf_method: &MemberInfo) -> Method {
        let mut method = Method::default();
        method.class = Some(class);
        method.copy_member_info(cf_method);
        method.copy_attributes(cf_method);
        let md = MethodDescriptorParser::parse_method_descriptor(&method.descriptor);
        method.calc_arg_slot_count(md.get_paramter_types());
        if method.is_native() {
            // 本地方法注入字节码和其他信息
            method.inject_code_attribute(md.get_return_type())   
        }
        method.parsed_descriptor = md;
        method
    }

    pub fn copy_attributes(&mut self, member_info: &MemberInfo) {
        let code_attr = member_info.code_attribute();
        if code_attr.is_some() {
            let attr = code_attr.unwrap();
            self.max_stack = attr.get_max_stack() as usize;
            self.max_locals = attr.get_max_locals() as usize;
            // TODO 目前复制字节码方式都是直接clone，后续修改。
            self.code = attr.get_code().clone();

            self.line_number_table = attr.line_number_table_attribute();

            let cp = unsafe { &**self.class.as_ref().unwrap() }.get_constant_pool().unwrap();
            self.exception_table = ExceptionTable::new_exception_table(attr.get_exception_table(), cp);
        }

        self.execeptions = member_info.exceptions_attribute();
        self.annotation_data = member_info.runtime_visible_annotations_attribute_data();
        self.parameter_annotation_data = member_info.runtime_visible_parameter_annotations_attribute_data();
        self.annotation_default_data = member_info.annotation_default_attribute_data();
    }

    // 计算参数数量
    fn calc_arg_slot_count(&mut self, parameter_types: &Vec<String>) {
        for param_type in parameter_types {
            self.arg_slot_count += 1;
            if param_type == "J" || param_type == "D" {
                self.arg_slot_count += 1;
            }
        }
        if !self.is_static() {
            self.arg_slot_count += 1;
        }
    }

    fn inject_code_attribute(&mut self, return_type: &str) {
        // 暂时赋值4
        self.max_stack = 4;
        // 本地方法帧的局部变量表只用来存放参数，与arg_slot_count相同即可
        self.max_locals = self.arg_slot_count;
        match &return_type[..1] {
            "V" => self.code = vec![0xfe, 0xb1], //return
            "D" => self.code = vec![0xfe, 0xaf], //dreturn
            "F" => self.code = vec![0xfe, 0xae], //freturn
            "J" => self.code = vec![0xfe, 0xad], //lreturn
            "L" | "[" => self.code = vec![0xfe, 0xb0], //areturn
            _ => self.code = vec![0xfe, 0xac], //ireturn
        }
    }

    // 查找异常处理项
    pub fn find_exception_handler(&self, ex_class: Arc<Class>, pc: i32) -> i32 {
        let handler = self.exception_table.find_exception_handler(ex_class, pc);
        if handler.is_some() {
            return handler.unwrap().handler_pc;
        }
        -1
    }

    pub fn get_line_number(&self, pc: i32) -> i32 {
        // 本地方法返回-2
        if self.is_native() {
            return -2;
        }
        // 没有行号返回-1
        if self.line_number_table.is_none() {
            return -1;
        }

        self.line_number_table.as_ref().clone().unwrap().get_line_number(pc)
    }

    // 访问标志判断方法
    pub fn is_synchronized(&self) -> bool {
        0 != self.access_flags & ACC_SYNCHRONIZED
    }

    pub fn is_bridge(&self) -> bool {
        0 != self.access_flags & ACC_BRIDGE
    }

    pub fn is_varargs(&self) -> bool {
        0 != self.access_flags & ACC_VARARGS
    }

    pub fn is_native(&self) -> bool {
        0 != self.access_flags & ACC_NATIVE
    }

    pub fn is_abstract(&self) -> bool {
        0 != self.access_flags & ACC_ABSTRACT
    }

    pub fn is_strict(&self) -> bool {
        0 != self.access_flags & ACC_STRICT
    }

    pub fn get_class_ptr(&self) -> Arc<Class> {
        self.class.clone().unwrap()
    }

    pub fn get_max_stack(&self) -> usize {
        self.max_stack
    }

    pub fn get_max_locals(&self) -> usize {
        self.max_locals
    }

    pub fn get_code(&self) -> &[u8] {
        &self.code
    }

    pub fn set_code(&mut self, code: Vec<u8>) {
        self.code = code;
    }

    pub fn get_code_vec(&self) -> Vec<u8> {
        self.code.clone()
    }

    pub fn get_arg_slot_count(&self) -> usize {
        self.arg_slot_count
    }

    pub fn get_parsed_desctiptor(&self) -> &MethodDescriptor {
        &self.parsed_descriptor
    }

    pub fn get_parameter_annotation_data(&self) -> &Vec<u8> {
        &self.parameter_annotation_data
    }

    pub fn get_annotation_default_data(&self) -> &Vec<u8> {
        &self.annotation_default_data
    }

    pub fn is_constructor(&self) -> bool {
        !self.is_static() && self.name == "<init>"
    }

    pub fn is_clinit(&self) -> bool {
        self.is_static() && self.name == "<clinit>"
    }

    // reflection
    pub fn parameter_types(&self) -> Vec<Arc<Class>> {
        if self.arg_slot_count == 0 {
            return vec![];
        }
        let class_loader = self.class.as_ref().unwrap().get_class_loader().unwrap();
        let param_types = self.parsed_descriptor.get_paramter_types();
        param_types.into_iter()
            .map(|param_type| to_class_name(param_type))
            .map(|param_type| class_loader.lock().unwrap().load_class(param_type))
            .collect()
    }

    pub fn return_type(&self) -> Arc<Class> {
        let return_type = self.parsed_descriptor.get_return_type();
        let reutn_class_name = to_class_name(return_type);
        self.class.as_ref().unwrap().get_class_loader().unwrap().lock().unwrap().load_class(reutn_class_name)
    }

    pub fn exception_types(&self) -> Vec<Arc<Class>> {
        if self.execeptions.is_none() {
            return vec![];
        }

        let ex_index_table = self.execeptions.as_ref().unwrap().exception_index_table();
        let cp = self.class.as_ref().unwrap().get_constant_pool().unwrap();
        ex_index_table.into_iter().map(|ex_index| {
            cp.get_constant(*ex_index as usize).unwrap().class_ref().lock().unwrap().resolved_class()
        }).collect()
    }
}

//  const _shim_class: *mut Class = Class::new_shim();
// static SHIM_CLASS: Lazy<Arc<Class>> = Lazy::new(|| {
//     Arc::new(Class::new_shim())
// });

impl Method {
    pub fn shim_return_method() -> Method {
        Method { 
            access_flags: ACC_STATIC, 
            name: "<return>".to_string(), 
            descriptor: "".to_string(), 
            signature: "".to_string(),
            annotation_data: vec![],
            class: Some(Arc::new(Class::new_shim())),
            max_stack: 0, 
            max_locals: 0, 
            code: vec![0xb1],  // return
            arg_slot_count: 0,  
            exception_table: ExceptionTable::default(), 
            line_number_table: None ,
            parsed_descriptor: MethodDescriptor::default(),
            ..Default::default()
        }
    }

    pub fn shim_return_method_specify_class(class: Arc<Class>) -> Method {
        Method { 
            access_flags: ACC_STATIC, 
            name: "<return>".to_string(), 
            descriptor: "".to_string(), 
            signature: "".to_string(),
            annotation_data: vec![],
            class: Some(class),
            max_stack: 0, 
            max_locals: 0, 
            code: vec![0xb1],  // return
            arg_slot_count: 0,  
            exception_table: ExceptionTable::default(), 
            line_number_table: None ,
            parsed_descriptor: MethodDescriptor::default(),
            ..Default::default()
        }
    }
    

}